﻿using System;

using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Surface.Core;
using Microsoft.Surface.Core.Manipulations;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;


namespace Sublimation
{
    class MenuManipulator : GameComponent
    {
        protected List<MenuSurf> menuList = new List<MenuSurf>();
        protected List<Contact> prevTagList = new List<Contact>();
        protected List<Contact> curTagList = new List<Contact>();

        protected WorldPropertiesSurf worldProperties;
        protected Game game;
        public MenuManipulator(Game game, WorldPropertiesSurf worldProperties)
            : base(game)
        {
            this.game = game;
            Game.Components.Add(this);
            this.worldProperties = worldProperties;
            UpdateOrder = 40;
        }
        private void CreateMenu(Contact hudContact)
        {
            MenuSurf hudMenu1 = new MenuSurf(worldProperties, hudContact,Vector2.Zero);
            hudMenu1.Position = new Vector2(hudContact.X, hudContact.Y);
            List<Tower> towers =  worldProperties.Players[0].Towers;
            hudMenu1.Rotation = hudContact.Orientation;
            hudMenu1.InitialisePreviewTowerItems(towers);
            hudMenu1.AlignAllItems(hudMenu1.Rotation);
            hudMenu1.InitialisePreviewTowers(towers);

            hudMenu1.CheckTowerCollision(new Vector2(hudContact.X,hudContact.Y));
            menuList.Add(hudMenu1);
        }

        private bool ContainsContact(List<Contact> tagList, Contact contact)
        {
            bool contains = false;
            foreach (Contact curContact in tagList)
            {
                if (curContact.Tag.Byte.Value == contact.Tag.Byte.Value)
                {
                    contains = true;
                }
            }
            return contains;
        }

        #region overrided methods
        public override void Initialize()
        {
            base.Initialize();
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            ReadOnlyContactCollection currentContacts = worldProperties.Contacts;

            foreach (Contact contact in currentContacts)
            {
                if (contact.IsTagRecognized)
                {
                    // add it to current tag list
                    curTagList.Add(contact);
                    if (menuList.Count != 0)
                    {
                        bool newHudCheck = true;

                        // update the menulist for new huds
                        foreach (MenuSurf aMenu in menuList)
                        {
                            if (aMenu.Contact.Tag.Byte.Value == contact.Tag.Byte.Value)
                            {
                                newHudCheck = false;
                                if (aMenu.Visible == false)
                                {
                                    aMenu.Visible = true;
                                    aMenu.AlignAllItems(contact.Orientation);
                                    aMenu.Rotation = contact.Orientation;
                                    foreach (MenuItem aItem in aMenu.MenuItemList)
                                    {
                                        // do not make preview towers visible
                                        if (!(aItem is PreviewTower))
                                            aItem.Visible = true;         
                                    }       
                                }
                                aMenu.CheckTowerCollision(new Vector2(contact.CenterX, contact.CenterY));
                            }
                        }
                        // if new hud is placed on the surface 
                        if (newHudCheck)
                        {
                            // create a new menu 
                            CreateMenu(contact);
                        }

                    }
                    // if it is the first hud contact
                    else
                    {
                        CreateMenu(contact);
                    }
                }
                /*
                 * Check finger contacts for each menu item 
                 */
                else if (contact.IsFingerRecognized)
                {
                        foreach (MenuSurf aMenu in menuList)
                        {
                            // if menu is on the surface, update
                            if (Game.Components.Contains(aMenu) && aMenu.Visible)
                            {
                                for (int i = 0; i < aMenu.MenuItemList.Count; i++)
                                {
                                    MenuItemSurf aItem = (MenuItemSurf)aMenu.MenuItemList.ElementAt(i);
                                    // if item hasn't got an associated contact
                                    if (aItem.ItemContact == null)
                                    {
                                        if (aItem.ItemStatus != MenuItemStatus.Selected)
                                        {
                                            // make collision check
                                            if (aItem.Contains(contact))
                                            {
                                                if (aItem is PreviewTowerItem)
                                                {
                                                    # region SELECTING TOWERS ON HUD
                                                    PreviewTowerItem pItem = (PreviewTowerItem)aItem;
                                                    if (pItem.Kind == PreviewTowerKind.Built)
                                                    {
                                                        if (pItem.ItemStatus == MenuItemStatus.Unselected && !aMenu.AddingTower)
                                                        {
                                                             // clear the menu view
                                                            aMenu.ClearSelectedItems();

                                                            // mark the item as selected so finger contacts on it are disabled
                                                            pItem.ItemStatus = MenuItemStatus.Selected;
                                                            aMenu.CurPreviewTowerItem = pItem;
                                                            pItem.ItemContact = contact;

                                                            if (pItem.OriginTower != null)
                                                            {
                                                                pItem.OriginTower.SpriteColor = Color.Red;
                                                                // display the preview tower of the selected tower
                                                                PreviewTower curPreTower = aMenu.FindPreviewTower(pItem.OriginTower);
                                                                aMenu.CurPreviewTower = curPreTower;
                                                                if (curPreTower != null)
                                                                    curPreTower.SetVisible(true);
                                                            }

                                                        }
                                                    }
                                                    #endregion

                                                    #region STARTING ADD TOWER ACTION
                                                    else if (pItem.Kind == PreviewTowerKind.Add && !aMenu.AddingTower)
                                                    {
                                                        // check if the big boss has come (haha !)
                                                        if (worldProperties.Spawning)
                                                        {
                                                            Vector2 contactCenter = new Vector2(
                                                                  contact.CenterX - pItem.Sprite.Width / 2, contact.CenterY - pItem.Sprite.Height / 2
                                                                );

                                                            // Create a temporary item which is on move
                                                            MenuItemSurf tempItem = new MenuItemSurf(worldProperties, aMenu, contactCenter, new Vector2(0, 0));
                                                            tempItem.Rotation = 0.0f;
                                                            
                                                            tempItem.ItemContact = contact;
                                                            // set the center but take that when it's on move sprite's size will change into account
                                                            tempItem.Center = new Vector2(tempItem.Position.X + tempItem.TowerButtom.Width / 2, tempItem.Position.Y + tempItem.TowerButtom.Height/2);
                                                            aMenu.MenuItemList.Add(tempItem);
                                                            tempItem.ItemStatus = MenuItemStatus.OnMove;

                                                            pItem.ItemStatus = MenuItemStatus.Selected;

                                                            aMenu.AddingTower = true;
                                                        }
                                                    }
                                                    #endregion 
                                                }
                                                else if (aItem is PreviewTower)
                                                {
                                                    PreviewTower previewTower = (PreviewTower)aItem;
                                                    if (previewTower.Visible && !aMenu.AddingTower)
                                                        previewTower.HasContact(contact);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                }
            } // end of currentContacts loop

            /* Find items out of the menu and create towers */
            foreach (MenuSurf aMenu in menuList)
            {
                if (Game.Components.Contains(aMenu) && aMenu.Visible)
                {
                    List<MenuItem> menuItemList = aMenu.MenuItemList;
                    for (int i = 0; i < menuItemList.Count; i++)
                    {
                        MenuItemSurf aItem = (MenuItemSurf)menuItemList.ElementAt(i);
                        Contact itemContact = aItem.ItemContact;

                        if (itemContact != null)
                        {
                            Contact tempContact;
                            if (currentContacts.TryGetContactFromId(itemContact.Id, out tempContact)
                                && aItem.ItemStatus == MenuItemStatus.OnMove)
                            {
                                // set the item position relative to contact's 
                                Vector2 contactCenter = new Vector2(
                                      tempContact.CenterX - aItem.Sprite.Width / 2, tempContact.CenterY - aItem.Sprite.Height / 2
                                    );
                                Vector2 tempPrevPos = new Vector2(aItem.Position.X, aItem.Position.Y);
                                aItem.Position = contactCenter;
                                aItem.Center += aItem.Position - tempPrevPos;
                            }
                            // if the item was associated with a contact but that contact is not on surface
                            else 
                            {
                                aItem.ItemContact = null;
                                if (aItem.ItemStatus == MenuItemStatus.OnMove)
                                {
                                    menuItemList.Remove(aItem);
                                    aItem.Kill();
                                    aMenu.AddingTower = false;
                                    List<Tower> towerList = worldProperties.Players[0].Towers;

                                    // check if the currently added tower intersects with other towers on the map
                                    bool towerInterCheck = false;
                                    foreach (Tower aTower in towerList)
                                    {
                                        if (aItem.IntersectTower(aTower))
                                        {
                                            towerInterCheck = true;
                                            break;
                                        }
                                    }


                                    Player player = worldProperties.Players[0];
                                    float addTowerDist = Vector2.Distance(aMenu.PreviewTowerItemList.ElementAt(player.Towers.Count).Center,aItem.Center);
                                    // if it is not intersecting with towers and not inside the menu, add it
                                    if (!towerInterCheck &&  addTowerDist > 50
                                        /* && !aMenu.ContainsPoint(itemCenter)*/)
                                    {
                                        player.addTower(aItem.Position.X + aItem.Sprite.Width / 2, aItem.Position.Y + aItem.Sprite.Height / 2, false);
                                        
                                        // associate new tower with its preview tower
                                        aMenu.AddPreviewTower(towerList.Last());
                                        // clear the menu view
                                        aMenu.ClearSelectedItems();

                                        //aMenu.PreviewTowerList.ElementAt(towerList.Count - 1).CurTower = towerList.Last();

                                        
                                        /*
                                        // add preview of tower in each menu
                                        foreach (MenuSurf curMenu in menuList)
                                        {
                                            // clear the view before add preview tower
                                            List<PreviewTower> preTowerList = curMenu.PreviewTowerList;
                                            foreach(PreviewTower aTower in preTowerList)
                                                aTower.SetVisible(false);

                                            curMenu.AddPreviewTowerItem(player.Towers.Last(),player.Towers.Count - 1); 
                                        }
                                        */
                                    }
                                    foreach (MenuItem item in menuItemList)
                                    {
                                        if (item.ItemStatus == MenuItemStatus.Selected)
                                        {
                                            item.ItemStatus = MenuItemStatus.Unselected;
                                            Tower aTower =  ((PreviewTowerItem)item).OriginTower;
                                            if (aTower != null)
                                                aTower.SpriteColor = Color.White;
                                        }
                                    }
                                }
                            }
                        }
                        else if (aItem is PreviewTower)
                        {
                            
                            PreviewTower previewTower = (PreviewTower)aItem;
                            if (previewTower.Visible)
                            {
                                previewTower.CheckDragFinished();
                                previewTower.CheckDeleteDragFinished();
                                previewTower.UpdateBuildProcess();
                            }
                        }
                    }
                }
            }

            #region CHECKING IF THE TAG IS REMOVED

            foreach (Contact tagContact in prevTagList)
            {
                // if the tag is removed
                if (!ContainsContact(curTagList, tagContact))
                {
                    // find the menu associated with that tag
                    for (int i = 0; i < menuList.Count; i++)
                    {
                        MenuSurf aMenu = menuList.ElementAt(i);
                        if (aMenu.Contact.Tag.Byte.Value == tagContact.Tag.Byte.Value)
                        {
                            // remove all menu items belong to the menu
                            foreach (MenuItem aItem in aMenu.MenuItemList)
                            {
                                if (aItem is PreviewTower)
                                {
                                    ((PreviewTower)aItem).SetVisible(false);
                                }
                                else
                                    aItem.Visible = false;

                                if (aItem is PreviewTowerItem)
                                {
                                    ((PreviewTowerItem)aItem).ItemStatus = MenuItemStatus.Unselected;
                                }
                            }

                            if (aMenu.CurPreviewTower != null)
                            {
                                if (aMenu.CurPreviewTower.CurTower != null)
                                {
                                    aMenu.CurPreviewTower.CurTower.SpriteColor = Color.White;
                                }
                                aMenu.CurPreviewTower = null;
                                aMenu.CurPreviewTowerItem = null;
                            }

                            aMenu.Visible = false;
                            aMenu.AlignAllItems(MathHelper.TwoPi - aMenu.Rotation);
                            aMenu.Rotation = 0.0f;
                            aMenu.PrevOrientation = 0.0f;
                            curTagList.Remove(tagContact);
                        }
                    }
                }
            }

            #endregion

            #region CHECKING IF ANY TOWER HAS BEEN DESTROYED

            List<Tower> towers = worldProperties.Players[0].Towers;
            int currentNumTowers = towers.Count();
            if(menuList.Count != 0)
            {
                // it is ok to check one menu since towers and their associated menu items are 
                // syncronized in all menus.
                MenuSurf aMenu = (MenuSurf)menuList.First();

                List<PreviewTowerItem> list =  aMenu.PreviewTowerItemList;
                // Find the towers that are destroyed
                for(int i = 0 ; i < list.Count; i++)
                {
                    PreviewTowerItem aItem = list.ElementAt(i);
                    if (aItem.Kind == PreviewTowerKind.Built)
                    {
                        // If the tower associated with Previewtower item's been destroyed
                        if (!towers.Contains(aItem.OriginTower))
                        {
                            // Find the preview item that holds the destroyed tower
                            PreviewTower deletedPreviewTower = aMenu.FindPreviewTower(aItem.OriginTower);

                            if (deletedPreviewTower != null)
                            {
                                // delete preview tower 
                                aMenu.PreviewTowerList.Remove(deletedPreviewTower);
                                aMenu.MenuItemList.Remove(deletedPreviewTower);

                                deletedPreviewTower.SetVisible(false);
                                deletedPreviewTower.CurTower = null;
                                deletedPreviewTower = null;
                            }

                            aMenu.UpdatePreviewTowerItemList();
                            break;
                            /*
                            // shift to left 
                            for (int j = i; j < list.Count - 1; j++)
                            {
                                // if preview item's tower is being set to null
                                // make the associated previewTower's tower also null
                                if (list[j + 1].OriginTower == null)
                                {
                                    if (list[j].OriginTower != null)
                                    {
                                        PreviewTower curPreTower = aMenu.FindPreviewTower(list[j].OriginTower);
                                        if (curPreTower != null)
                                        {
                                            curPreTower.SetVisible(false);
                                            curPreTower.CurTower = null;
                                        }
                                    }
                                }
                                list[j].OriginTower = list[j + 1].OriginTower;
                                list[j].Kind = list[j + 1].Kind;
                                list[j].ItemStatus = list[j + 1].ItemStatus;
                            }
                            PreviewTowerItem lastPreItem = list[list.Count - 1];
                            if (lastPreItem.Kind == PreviewTowerKind.Built)
                            {
                                lastPreItem.Kind = PreviewTowerKind.Add;
                                if (lastPreItem.OriginTower != null)
                                {
                                    PreviewTower curPreTower = aMenu.FindPreviewTower(lastPreItem.OriginTower);

                                    if (curPreTower != null)
                                    {
                                        //curPreTower.CurTower = null;
                                        curPreTower.SetVisible(false);
                                    }
                                }
                                //lastPreItem.OriginTower = null;
                                lastPreItem.ItemStatus = MenuItemStatus.Unselected;
                            }
                            else if (lastPreItem.Kind == PreviewTowerKind.Add)
                                lastPreItem.Kind = PreviewTowerKind.Unbuilt; 
                             */
                        }
                    }
                }

                /* Part for multiple huds
                if(changeCheck)
                {
                    // Now apply the changes also to other huds to synchronize
                    MenuSurf changedMenu = menuList.ElementAt(0);
                    List<PreviewTowerItem> changedPreTowerItemList = changedMenu.PreviewTowerItemList;
                    List<PreviewTower> changedPreTowerList = changedMenu.PreviewTowerList;
                    for (int i = 1; i < menuList.Count(); i++)
                    {
                        MenuSurf curMenu = menuList.ElementAt(i);
                        // PreviewTowerItem changes
                        List<PreviewTowerItem> preItemList = curMenu.PreviewTowerItemList;
                        for (int j = 0; j < preItemList.Count(); j++)
                        {
                            PreviewTowerItem aItem = preItemList.ElementAt(j);
                            PreviewTowerItem changedItem = changedPreTowerItemList.ElementAt(j);
                            aItem.OriginTower = changedItem.OriginTower;
                            aItem.Kind = changedItem.Kind;
                            aItem.ItemStatus = changedItem.ItemStatus;
                        }

                        // Pretower changes 
                        List<PreviewTower> preList = curMenu.PreviewTowerList;
                        for (int j = 0; j < preList.Count(); j++)
                        {
                            PreviewTower aItem = preList.ElementAt(j);
                            PreviewTower changedItem = changedPreTowerList.ElementAt(j);
                            aItem.CurTower = changedItem.CurTower;
                            aItem.SetVisible(changedItem.Visible);
                        }
                    }
                   }
                 */
                }  
                 
            #endregion

            #region TRANSFORMING MENUS
            foreach (Contact contact in curTagList)
            {
                // update each hud menu
                foreach (MenuSurf aMenu in menuList)
                {
                    if (aMenu.Contact.Tag.Byte.Value == contact.Tag.Byte.Value)
                    {
                        aMenu.Transform(contact);
                    }
                }
            }

            #endregion

            // save curTagList 
            prevTagList.Clear();
            prevTagList = new List<Contact>(curTagList);

            // clear the current tag list
            curTagList.Clear();
        }
        #endregion
    }
}
